package org.dromara.nursing.service.impl;

import org.dromara.common.core.utils.MapstructUtils;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.mybatis.core.page.PageQuery;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.RequiredArgsConstructor;
import org.dromara.nursing.domain.vo.ElderOutstandingFeesVo;
import org.springframework.stereotype.Service;
import org.dromara.nursing.domain.bo.FeeRecordBo;
import org.dromara.nursing.domain.vo.FeeRecordVo;
import org.dromara.nursing.domain.FeeRecord;
import org.dromara.nursing.mapper.FeeRecordMapper;
import org.dromara.nursing.mapper.ElderBasicMapper;
import org.dromara.nursing.domain.ElderBasic;
import org.dromara.nursing.service.IFeeRecordService;
import org.dromara.nursing.domain.bo.ElderOutstandingFeesBo;
import org.dromara.nursing.service.IElderOutstandingFeesService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.List;
import java.util.Map;
import java.util.Collection;
import java.util.Date;
import java.util.Calendar;
import java.util.Objects;
import cn.hutool.core.collection.CollUtil;
import java.util.Collections;
import java.time.LocalDateTime;

/**
 * 费用记录Service业务层处理
 *
 * @author Xue
 * @date 2025-04-01
 */
@RequiredArgsConstructor
@Service
public class FeeRecordServiceImpl implements IFeeRecordService {

    private final FeeRecordMapper baseMapper;
    private final IElderOutstandingFeesService elderOutstandingFeesService;
    private final ElderBasicMapper elderBasicMapper;
    private static final Logger log = LoggerFactory.getLogger(FeeRecordServiceImpl.class);

    /**
     * 查询费用记录
     *
     * @param recordId 主键
     * @return 费用记录
     */
    @Override
    public FeeRecordVo queryById(Long recordId){
        return baseMapper.selectVoById(recordId);
    }

    /**
     * 分页查询费用记录列表
     *
     * @param bo        查询条件
     * @param pageQuery 分页参数
     * @return 费用记录分页列表
     */
    @Override
    public TableDataInfo<FeeRecordVo> queryPageList(FeeRecordBo bo, PageQuery pageQuery) {
        LambdaQueryWrapper<FeeRecord> lqw = buildQueryWrapper(bo);
        Page<FeeRecordVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
        return TableDataInfo.build(result);
    }

    /**
     * 查询符合条件的费用记录列表
     *
     * @param bo 查询条件
     * @return 费用记录列表
     */
    @Override
    public List<FeeRecordVo> queryList(FeeRecordBo bo) {
        LambdaQueryWrapper<FeeRecord> lqw = buildQueryWrapper(bo);
        return baseMapper.selectVoList(lqw);
    }

    private LambdaQueryWrapper<FeeRecord> buildQueryWrapper(FeeRecordBo bo) {
        Map<String, Object> params = bo.getParams();
        LambdaQueryWrapper<FeeRecord> lqw = Wrappers.lambdaQuery();
        lqw.orderByAsc(FeeRecord::getRecordId);
        lqw.like(StringUtils.isNotBlank(bo.getElderName()), FeeRecord::getElderName, bo.getElderName());
        lqw.eq(StringUtils.isNotBlank(bo.getFeeType()), FeeRecord::getFeeType, bo.getFeeType());
        lqw.eq(bo.getAmount() != null, FeeRecord::getAmount, bo.getAmount());
        return lqw;
    }

    /**
     * 新增费用记录
     *
     * @param bo 费用记录
     * @return 是否新增成功
     */
    @Override
    public Boolean insertByBo(FeeRecordBo bo) {
        if (bo.getElderId() == null) {
            log.error("添加费用记录失败：老人ID不能为空");
            return false;
        }
        
        log.info("开始添加费用记录: 老人ID={}, 老人姓名={}, 费用类型={}, 金额={}, 支付状态={}",
                 bo.getElderId(), bo.getElderName(), bo.getFeeType(), bo.getAmount(), bo.getPaymentStatus());
        
        FeeRecord add = MapstructUtils.convert(bo, FeeRecord.class);
        validEntityBeforeSave(add);
        try {
            boolean flag = baseMapper.insert(add) > 0;
            if (flag) {
                bo.setRecordId(add.getRecordId());
                log.info("费用记录添加成功，记录ID: {}", bo.getRecordId());
                
                // 判断支付状态，如果是未支付或部分支付，自动创建欠费记录
                String paymentStatus = bo.getPaymentStatus();
                log.info("支付状态类型: {}, 值: {}", paymentStatus != null ? paymentStatus.getClass().getName() : "null", paymentStatus);
                
                if (paymentStatus != null && ("未支付".equals(paymentStatus) || "0".equals(paymentStatus) || 
                    "部分支付".equals(paymentStatus) || "2".equals(paymentStatus))) {
                    log.info("检测到非全额支付状态[{}]，准备创建欠费记录", paymentStatus);
                    createOutstandingFee(add);
                } else {
                    log.info("当前支付状态[{}]不需要创建欠费记录", paymentStatus);
                }
            } else {
                log.error("费用记录添加失败");
            }
            return flag;
        } catch (Exception e) {
            log.error("添加费用记录异常: {}", e.getMessage(), e);
            return false;
        }
    }

    /**
     * 创建欠费记录
     *
     * @param feeRecord 费用记录
     */
    private void createOutstandingFee(FeeRecord feeRecord) {
        log.info("开始创建欠费记录，费用记录ID：{}，老人ID：{}，支付状态：{}", 
                feeRecord.getRecordId(), feeRecord.getElderId(), feeRecord.getPaymentStatus());
                
        // 检查必要字段是否为空
        if (feeRecord.getElderId() == null) {
            log.error("无法创建欠费记录：老人ID为空");
            return;
        }
        
        if (feeRecord.getRecordId() == null) {
            log.error("无法创建欠费记录：费用记录ID为空");
            return;
        }
        
        // 支付状态为"已支付"时，不需要创建欠费记录
        if ("已支付".equals(feeRecord.getPaymentStatus())) {
            log.info("支付状态为'已支付'，不需要创建欠费记录");
            return;
        }
        
        try {
            // 创建欠费记录对象
            ElderOutstandingFeesBo outstandingFeesBo = new ElderOutstandingFeesBo();
            
            // 设置老人信息
            ElderBasic elder = elderBasicMapper.selectById(feeRecord.getElderId());
            if (elder != null) {
                log.info("查询到老人信息：ID={}, 姓名={}", elder.getElderId(), elder.getElderName());
                outstandingFeesBo.setElderId(elder.getElderId());
                outstandingFeesBo.setElderName(elder.getElderName());
            } else {
                log.warn("未查询到老人信息，使用费用记录中的信息");
                outstandingFeesBo.setElderId(feeRecord.getElderId());
                outstandingFeesBo.setElderName(feeRecord.getElderName());
            }
            
            // 设置来源ID和费用类型
            outstandingFeesBo.setSourceId(feeRecord.getRecordId());
            log.info("设置来源ID：{}", feeRecord.getRecordId());
            outstandingFeesBo.setFeeSource("费用记录");
            // 不设置feeDescription字段，避免数据过长问题
            outstandingFeesBo.setPaymentStatus(feeRecord.getPaymentStatus());
            
            // 设置总金额
            outstandingFeesBo.setTotalAmount(feeRecord.getAmount());
            
            // 根据支付状态设置已付金额和欠费金额
            if ("未支付".equals(feeRecord.getPaymentStatus())) {
                outstandingFeesBo.setPaidAmount(0L);
                outstandingFeesBo.setOutstandingAmount(feeRecord.getAmount());
                log.info("未支付状态：总金额={}，已付金额=0，欠费金额={}", 
                        outstandingFeesBo.getTotalAmount(), outstandingFeesBo.getOutstandingAmount());
            } else if ("部分支付".equals(feeRecord.getPaymentStatus())) {
                // 假设部分支付为总金额的一半
                Long paidAmount = feeRecord.getAmount() / 2;
                outstandingFeesBo.setPaidAmount(paidAmount);
                outstandingFeesBo.setOutstandingAmount(feeRecord.getAmount() - paidAmount);
                log.info("部分支付状态：总金额={}，已付金额={}，欠费金额={}", 
                        outstandingFeesBo.getTotalAmount(), outstandingFeesBo.getPaidAmount(), 
                        outstandingFeesBo.getOutstandingAmount());
            }
            
            // 保存欠费记录
            boolean success = elderOutstandingFeesService.insertByBo(outstandingFeesBo);
            if (success) {
                log.info("欠费记录创建成功，来源ID：{}", feeRecord.getRecordId());
            } else {
                log.error("欠费记录创建失败，来源ID：{}", feeRecord.getRecordId());
            }
        } catch (Exception e) {
            log.error("创建欠费记录时发生异常，费用记录ID：{}，异常信息：{}", 
                    feeRecord.getRecordId(), e.getMessage(), e);
        }
    }

    /**
     * 修改费用记录
     *
     * @param bo 费用记录
     * @return 是否修改成功
     */
    @Override
    public Boolean updateByBo(FeeRecordBo bo) {
        if (bo.getRecordId() == null) {
            log.error("修改费用记录失败：记录ID不能为空");
            return false;
        }
        
        log.info("开始修改费用记录: 记录ID={}, 老人ID={}, 老人姓名={}, 费用类型={}, 金额={}, 支付状态={}",
                 bo.getRecordId(), bo.getElderId(), bo.getElderName(), bo.getFeeType(), bo.getAmount(), bo.getPaymentStatus());
        
        try {
            // 先查询原始记录以获取之前的支付状态
            FeeRecordVo oldRecord = queryById(bo.getRecordId());
            if (oldRecord == null) {
                log.error("修改失败：未找到ID为{}的费用记录", bo.getRecordId());
                return false;
            }
            
            FeeRecord update = MapstructUtils.convert(bo, FeeRecord.class);
            validEntityBeforeSave(update);
            boolean result = baseMapper.updateById(update) > 0;
            
            if (result) {
                log.info("费用记录修改成功");
                
                // 如果支付状态由"未支付"或"部分支付"改为"已支付"，更新欠费记录
                if (("未支付".equals(oldRecord.getPaymentStatus()) || "0".equals(oldRecord.getPaymentStatus()) || 
                     "部分支付".equals(oldRecord.getPaymentStatus()) || "2".equals(oldRecord.getPaymentStatus()))
                    && ("已支付".equals(bo.getPaymentStatus()) || "1".equals(bo.getPaymentStatus()))) {
                    log.info("支付状态从未支付/部分支付变为已支付，更新欠费记录");
                    updateOutstandingFee(update);
                }
                // 如果之前不是欠费状态，但现在变成欠费状态，创建欠费记录
                else if (!"未支付".equals(oldRecord.getPaymentStatus()) && !"0".equals(oldRecord.getPaymentStatus()) && 
                         !"部分支付".equals(oldRecord.getPaymentStatus()) && !"2".equals(oldRecord.getPaymentStatus())
                         && ("未支付".equals(bo.getPaymentStatus()) || "0".equals(bo.getPaymentStatus()) || 
                             "部分支付".equals(bo.getPaymentStatus()) || "2".equals(bo.getPaymentStatus()))) {
                    log.info("支付状态从已支付变为未支付/部分支付，创建新的欠费记录");
                    createOutstandingFee(update);
                }
                // 如果支付状态依然是欠费状态但有变化，更新欠费记录
                else if (("未支付".equals(oldRecord.getPaymentStatus()) || "0".equals(oldRecord.getPaymentStatus()) || 
                          "部分支付".equals(oldRecord.getPaymentStatus()) || "2".equals(oldRecord.getPaymentStatus()))
                         && ("未支付".equals(bo.getPaymentStatus()) || "0".equals(bo.getPaymentStatus()) || 
                             "部分支付".equals(bo.getPaymentStatus()) || "2".equals(bo.getPaymentStatus()))
                         && !oldRecord.getPaymentStatus().equals(bo.getPaymentStatus())) {
                    log.info("支付状态在欠费状态之间变化，更新欠费记录");
                    updateOutstandingFee(update);
                }
            } else {
                log.error("费用记录修改失败");
            }
            
            return result;
        } catch (Exception e) {
            log.error("修改费用记录异常: {}", e.getMessage(), e);
            return false;
        }
    }

    /**
     * 更新欠费记录
     *
     * @param updateFeeRecord 新费用记录
     */
    private void updateOutstandingFee(FeeRecord updateFeeRecord) {
        log.info("开始更新欠费记录，费用记录ID：{}，老人ID：{}", updateFeeRecord.getRecordId(), updateFeeRecord.getElderId());

        try {
            // 查询关联的欠费记录
            ElderOutstandingFeesBo queryBo = new ElderOutstandingFeesBo();
            queryBo.setSourceId(updateFeeRecord.getRecordId());
            log.info("查询欠费记录条件: sourceId={}", updateFeeRecord.getRecordId());
            
            List<ElderOutstandingFeesVo> feesVoList = elderOutstandingFeesService.queryList(queryBo);
            log.info("查询到关联的欠费记录数量: {}", feesVoList != null ? feesVoList.size() : 0);

            if (CollUtil.isNotEmpty(feesVoList)) {
                // 存在关联的欠费记录，需要根据支付状态决定更新或删除
                ElderOutstandingFeesVo outstandingFee = feesVoList.get(0);
                
                // 如果新的支付状态为"已支付"，则删除欠费记录
                if ("已支付".equals(updateFeeRecord.getPaymentStatus())) {
                    log.info("新支付状态为'已支付'，删除欠费记录: {}", outstandingFee.getRecordId());
                    List<Long> ids = Collections.singletonList(outstandingFee.getRecordId());
                    boolean deleteResult = elderOutstandingFeesService.deleteWithValidByIds(ids, false);
                    log.info("删除欠费记录结果: {}", deleteResult ? "成功" : "失败");
                } else {
                    // 支付状态为"未支付"或"部分支付"，更新欠费记录
                    log.info("更新欠费记录: {}", outstandingFee.getRecordId());
                    ElderOutstandingFeesBo updateBo = new ElderOutstandingFeesBo();
                    updateBo.setRecordId(outstandingFee.getRecordId());
                    updateBo.setPaymentStatus(updateFeeRecord.getPaymentStatus());
                    updateBo.setTotalAmount(updateFeeRecord.getAmount());
                    
                    // 根据支付状态设置已付金额和欠费金额
                    if ("未支付".equals(updateFeeRecord.getPaymentStatus())) {
                        updateBo.setPaidAmount(0L);
                        updateBo.setOutstandingAmount(updateFeeRecord.getAmount());
                        log.info("未支付状态：已付金额=0，欠费金额={}", updateBo.getOutstandingAmount());
                    } else if ("部分支付".equals(updateFeeRecord.getPaymentStatus())) {
                        // 部分支付的情况，假设为总金额的一半
                        Long paidAmount = updateFeeRecord.getAmount() / 2;
                        updateBo.setPaidAmount(paidAmount);
                        updateBo.setOutstandingAmount(updateFeeRecord.getAmount() - paidAmount);
                        log.info("部分支付状态：已付金额={}，欠费金额={}", 
                                updateBo.getPaidAmount(), updateBo.getOutstandingAmount());
                    }
                    
                    boolean updateResult = elderOutstandingFeesService.updateByBo(updateBo);
                    log.info("更新欠费记录结果: {}", updateResult ? "成功" : "失败");
                }
            } else {
                // 不存在关联的欠费记录
                log.info("未查询到关联的欠费记录");
                
                // 如果新的支付状态不是"已支付"，则创建欠费记录
                if (!"已支付".equals(updateFeeRecord.getPaymentStatus())) {
                    log.info("新支付状态为'{}'，需要创建欠费记录", updateFeeRecord.getPaymentStatus());
                    // 使用更新后的费用记录创建欠费记录
                    createOutstandingFee(updateFeeRecord);
                } else {
                    log.info("新支付状态为'已支付'，无需创建欠费记录");
                }
            }
        } catch (Exception e) {
            log.error("更新欠费记录时发生异常: {}", e.getMessage(), e);
        }
    }

    /**
     * 保存前的数据校验
     */
    private void validEntityBeforeSave(FeeRecord entity){
        //TODO 做一些数据校验,如唯一约束
    }

    /**
     * 校验并批量删除费用记录信息
     *
     * @param ids     待删除的主键集合
     * @param isValid 是否进行有效性校验
     * @return 是否删除成功
     */
    @Override
    public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
        if(isValid){
            //TODO 做一些业务上的校验,判断是否需要校验
        }

        // 删除相关的欠费记录
        for (Long id : ids) {
            deleteRelatedOutstandingFees(id);
        }

        return baseMapper.deleteByIds(ids) > 0;
    }

    /**
     * 删除相关联的欠费记录
     *
     * @param feeRecordId 费用记录ID
     */
    private void deleteRelatedOutstandingFees(Long feeRecordId) {
        log.info("开始删除关联的欠费记录，费用记录ID: {}", feeRecordId);
        
        // 查询关联的欠费记录
        ElderOutstandingFeesBo queryBo = new ElderOutstandingFeesBo();
        queryBo.setSourceId(feeRecordId);
        log.info("查询条件：sourceId={}", feeRecordId);
        
        List<ElderOutstandingFeesVo> feesVoList = elderOutstandingFeesService.queryList(queryBo);
        log.info("查询到关联的欠费记录数量: {}", feesVoList != null ? feesVoList.size() : 0);

        if (CollUtil.isNotEmpty(feesVoList)) {
            // 收集欠费记录ID
            List<Long> outstandingFeeIds = feesVoList.stream()
                .map(ElderOutstandingFeesVo::getRecordId)
                .toList();
            
            log.info("准备删除的欠费记录ID: {}", outstandingFeeIds);

            // 删除欠费记录
            if (!outstandingFeeIds.isEmpty()) {
                try {
                    boolean result = elderOutstandingFeesService.deleteWithValidByIds(outstandingFeeIds, false);
                    log.info("删除欠费记录结果: {}", result ? "成功" : "失败");
                } catch (Exception e) {
                    log.error("删除欠费记录时发生异常: {}", e.getMessage(), e);
                }
            }
        } else {
            log.info("未找到关联的欠费记录，无需删除");
        }
    }
}
